home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / SDKs / Word Services SDK 1.0.6 / Word Services XCMD 1.0d2 / Sources / DoBatchEvt.c next >
Encoding:
C/C++ Source or Header  |  1996-04-28  |  9.8 KB  |  404 lines  |  [TEXT/CWIE]

  1. // DoBatchEvt.c
  2. // Copyright © Michael D. Crawford.  All Rights Reserved.
  3. // mail bug reports and enhancement suggestions to crawford@scruznet.com
  4. // get updates from:
  5. // http://www.scruznet.com/~crawford/WordServices/wdsvindex.html
  6. // DoBatchEvt creatorCode [ fieldNumber ] [ cardNumber ]
  7. // Optional params default to 1.
  8. //
  9. //    Version history
  10. //  1.0d2    MDC        Added params for card and field number
  11. //    1.0d1    MDC        First release
  12.  
  13. #include <HyperXCMD.h>
  14. #include <Aliases.h>
  15. #include <Processes.h>
  16. #include <AppleEvents.h>
  17. #include <AEObjects.h>
  18. #include <AEPackObject.h>
  19. #include <AERegistry.h>
  20.  
  21. #include "TestBedPrefix.h"
  22. #include "FindProcess.h"
  23. #include "Gripe.h"
  24. #include "WordServices.h"
  25.  
  26. OSErr DoBatchCheck( AEAddressDesc *spellerAddrPtr, long fieldNumber, long cardNumber );
  27. OSErr CreateTextSpecifier( long windowNumber, long textNumber, AEDesc *specPtr );
  28. OSErr BuildWindowSpecifier( AEDesc *specPtr, long whichWindow );
  29. OSErr CreateFieldSpecifier( long cardNumber, long fieldNumber, AEDesc *specPtr );
  30. OSErr BuildCardSpecifier( AEDesc *specPtr, long whichWindow );
  31. void HandleStrToPStr( Handle h, StringPtr str );
  32.  
  33. #define kBatchTimeout    600
  34.  
  35. #ifdef XCMD_TESTBED
  36. void CallXCmd( XCmdPtr pBPtr )
  37. #else
  38. void main( XCmdPtr pBPtr )
  39. #endif
  40. {
  41.     OSType                signature;
  42.     ProcessSerialNumber psn;
  43.     ProcessInfoRec        pInfo;
  44.     OSErr                err;
  45.     AEAddressDesc        spellerAddr;
  46.     long                cardNumber;
  47.     long                fieldNumber;
  48.     Str255                strBuf;
  49.  
  50.     if ( pBPtr->paramCount < 1 || pBPtr->paramCount > 3 ){
  51.         pBPtr->returnValue = NewHandle( 9 );
  52.         if ( pBPtr->returnValue )
  53.             BlockMoveData( "paramErr", *( pBPtr->returnValue ), 9 );
  54.     }
  55.     
  56.     BlockMove( *( pBPtr->params[ 0 ] ), &signature, 4 );
  57.     
  58.     // Defaults
  59.     
  60.     cardNumber = 1;
  61.     fieldNumber = 1;
  62.  
  63.     if ( pBPtr->paramCount > 1 ){
  64.         HandleStrToPStr( pBPtr->params[ 1 ], strBuf );
  65.         StringToNum( strBuf, &fieldNumber );        
  66.     }
  67.     
  68.     if ( pBPtr->paramCount > 2 ){
  69.         HandleStrToPStr( pBPtr->params[ 2 ], strBuf );
  70.         StringToNum( strBuf, &cardNumber );        
  71.     
  72.     }
  73.     // Check if the speller is already running
  74.  
  75.     if ( !FindAProcess( signature, &psn, &pInfo, (FSSpecPtr)NULL, (StringPtr)NULL ) ){
  76.  
  77. //        err = LaunchSpeller( aliasHdl );
  78. //        if ( err ){
  79. //            Gripe( "\pUnable to launch Word Services server" );
  80. //            return err;
  81. //        }
  82.     }    
  83.  
  84.     err = AECreateDesc( typeApplSignature,
  85.                         (Ptr)&signature,
  86.                         sizeof( signature ),
  87.                         &spellerAddr );
  88.     if ( err ){
  89.         Gripe( "\pAECreateDesc failed" );
  90.         return;
  91.     }
  92.  
  93.     err = DoBatchCheck( &spellerAddr, fieldNumber, cardNumber );
  94.     if ( err ){
  95.         DebugStr( "\pDoBatchCheck failed" );
  96.         return;
  97.     }
  98.     
  99.     return;
  100. }
  101.  
  102. OSErr DoBatchCheck( AEAddressDesc *spellerAddrPtr, long fieldNumber, long cardNumber )
  103. {
  104.     OSErr            err;
  105. //    AEDesc            textSpecifier;
  106.     AEDesc            fieldSpecifier;
  107.     AppleEvent        btchEvent;
  108.     AppleEvent        replyEvent;
  109. //    WWJrPrefsHdl    prefHdl;
  110.     AEDescList        textSpecList;            /* 1.0d7 */
  111.     long            index;                    /* 1.0d7 */
  112.  
  113.     /* We make an object specifier that refers to _our_own_ window
  114.      */
  115.  
  116. //    err = CreateTextSpecifier( 1L, 1L, &textSpecifier );
  117.     err = CreateFieldSpecifier( cardNumber, fieldNumber, &fieldSpecifier );
  118.     
  119.     if ( err ){
  120.         Gripe( "\pCreateFieldSpecifier failed" );
  121.         return err;
  122.     }
  123.  
  124. //    prefHdl = GetPrefHandle();
  125. //    if ( !prefHdl ){
  126. //        Gripe( "\pCannot get preferences handle" );
  127. //        return resNotFound;
  128. //    }
  129. //    
  130. //    if ( (*prefHdl)->checkSel ){
  131. //        /* Make a formRange descriptor that gives the selection range */
  132. //
  133. //        Gripe( "\pSelection-only checking is not yet implemented" );
  134. //        return noErr;
  135. //    }
  136.  
  137.     /* Create the event to send to the speller */
  138.     
  139.     err = AECreateAppleEvent( kWordServicesClass,
  140.                                 kWSBatchCheckMe,
  141.                                 spellerAddrPtr,
  142.                                 kAutoGenerateReturnID,
  143.                                 kAnyTransactionID,
  144.                                 &btchEvent );
  145.     
  146.     if ( err ){
  147.         Gripe( "\pcreate btch event failed" );
  148.         return err;
  149.     }
  150.     err = AEDisposeDesc( spellerAddrPtr );
  151.     if ( err ){
  152.         Gripe( "\pAEDisposeDesc failed" );
  153.         return err;
  154.     }
  155.  
  156.  
  157.     /* 1.0d7 This is the new way to do it - use a list of object specifiers (even if
  158.      * only one of them
  159.      */
  160.     
  161.     err = AECreateList( (Ptr)NULL, (Size)0, false, &textSpecList );
  162.     if ( err ){
  163.         Gripe( "\pAECreateList failed" );
  164.         return err;
  165.     }
  166.     
  167.     /* Put our specifier into it.  If we had multiple text blocks to check, we would
  168.      * put specifiers for each into it in turn.
  169.      * Note that we use AEPutDesc, not AEPutParamDesc, to put items into an indexed
  170.      * list.
  171.      */
  172.  
  173. #define N_TEXT_SPECS    1L /*3L    */    /* Define this to be 1 for normal checking */
  174.  
  175.     for ( index = 1L; index <= N_TEXT_SPECS; index++ ){
  176.         err = AEPutDesc( &textSpecList,
  177.                             index,
  178.                             &fieldSpecifier );
  179.         if ( err ){
  180.             Gripe( "\pAEPutDesc failed to put text specifier into textSpecList" );
  181.             return err;
  182.         }
  183.     }
  184.  
  185.     err = AEDisposeDesc( &fieldSpecifier );
  186.     if ( err ){
  187.         Gripe( "\pAEDisposeDesc failed" );
  188.         return err;
  189.     }
  190.  
  191.     /* Insert the list of object specifiers as the direct object of the batch event */
  192.  
  193.     err = AEPutParamDesc( &btchEvent,
  194.                             keyDirectObject,
  195.                             &textSpecList );
  196.     if ( err ){
  197.         Gripe( "\pAEPutParamDesc failed to put direct object on batch event" );
  198.         return err;
  199.     }
  200.     
  201.     /* 1.0.3 MDC fixed a bug in which we disposed of textSpecifier a second
  202.      * time, instead of properly disposing of textSpecList
  203.      */
  204.  
  205.     err = AEDisposeDesc( &textSpecList );
  206.     if ( err ){
  207.         Gripe( "\pAEDisposeDesc failed" );
  208.         return err;
  209.     }
  210.  
  211.     /* Send the event.  We await the reply, so that if there is a failure of some
  212.      * sort in the initial connection, we can alert the user right away.  The timeout
  213.      * value to use here should be as long as one would care to have a user wait for
  214.      * the completion of a menu command.  Since we expect that the speller is on a local
  215.      * machine in this case, and should be able to respond immediately, we just give
  216.      * a few seconds for the timeout.
  217.      *
  218.      * We should assign an idle proc to spin the cursor.  Even better would be a progress
  219.      * dialog that says "Contacting speller" or some such, with an animated display that
  220.      * shows the time elapsed relative to the total timeout, so the user will know how
  221.      * long she may have to wait
  222.      */
  223.     
  224.     err = AESend( &btchEvent,
  225.                     &replyEvent,
  226.                     kAEWaitReply + kAECanInteract + kAECanSwitchLayer,
  227.                     kAENormalPriority,
  228.                     kBatchTimeout,
  229.                     (AEIdleUPP)NULL,
  230.                     (AEFilterUPP)NULL );
  231.     
  232.     if ( err ){
  233.         Gripe( "\psend batch event failed" );
  234.         return err;
  235.     }
  236.     err = AEDisposeDesc( &btchEvent );
  237.     if ( err ){
  238.         Gripe( "\pAEDisposeDesc failed" );
  239.         return err;
  240.     }
  241.     
  242.     /* MDC 1.1.1 fix a memory leak */
  243.  
  244.     err = AEDisposeDesc( &replyEvent );
  245.     if ( err ){
  246.         Gripe( "\pAEDisposeDesc failed" );
  247.         return err;
  248.     }
  249.     
  250.     /* Now the event has been sent.  There is nothing more that we have to actually do
  251.      * on our own initiative to accomplish the spelling; we just sit back and respond
  252.      * to events.  In particular, we don't remember that spelling is taking place - once
  253.      * the spelling is done, we will just start seeing events from the user (mouse and
  254.      * key clicks and so on
  255.      */
  256.     
  257.     return noErr;
  258. }
  259.  
  260. /*
  261.  * Descriptor packing routines
  262.  */
  263.  
  264. /* Create a formAbsolutePosition window descriptor */
  265.  
  266. OSErr BuildCardSpecifier( AEDesc *specPtr, long whichWindow )
  267. {
  268.     AEDesc    nullDesc;
  269.     AEDesc    nullSpec;
  270.     AEDesc    whichDesc;
  271.     OSErr    err;
  272.     
  273.     /* Create the descriptor for the container (the application, or null) */
  274.  
  275.     err = AECreateDesc( typeNull, (Ptr)NULL, (Size)0, &nullDesc );
  276.     if ( err )
  277.         return err;
  278.     
  279.     /* Create the key data, which gives the window number */
  280.     
  281.     err = CreateOffsetDescriptor( whichWindow, &whichDesc );
  282.     if ( err )
  283.         return err;
  284.  
  285.     /* Create the Object Specifier for the window */
  286.     
  287.     err = CreateObjSpecifier( 'cCRD',
  288.                                 &nullDesc,
  289.                                 formAbsolutePosition,
  290.                                 &whichDesc,
  291.                                 true,                    /* Dispose of input descriptors */
  292.                                 specPtr );                /* specPtr is the value we return */
  293.     return err;
  294. }
  295.  
  296. #ifdef NEVER
  297. OSErr CreateTextSpecifier( long windowNumber, long textNumber, AEDesc *specPtr )
  298. {
  299.     AEDesc    docSpecifier;
  300.     AEDesc    textDescriptor;
  301.     OSErr    err;
  302.  
  303.     /* Create an object specifier for a particular text field within a particular
  304.      * window. In each case use formAbsolutePosition.
  305.      */
  306.  
  307.     err = BuildWindowSpecifier( &docSpecifier, windowNumber );
  308.     if ( err ){
  309.         Gripe( "\pBuildWindowDescriptor failed" );
  310.         return err;
  311.     }
  312.     
  313.     err = CreateOffsetDescriptor( textNumber, &textDescriptor );
  314.     if ( err ){
  315.         Gripe( "\pCreateOffsetDescriptor failed" );
  316.         return err;
  317.     }
  318.     
  319.     err = CreateObjSpecifier( cText,
  320.                                 &docSpecifier,
  321.                                 formAbsolutePosition,
  322.                                 &textDescriptor,
  323.                                 true,                        /* Dispose input descriptors */
  324.                                 specPtr );
  325.     if ( err ){
  326.         Gripe( "\pCreateObjSpecifer failed" );
  327.         return err;
  328.     }
  329.  
  330.     return noErr;
  331. }
  332. #endif
  333.  
  334. OSErr CreateFieldSpecifier( long cardNumber, long fieldNumber, AEDesc *specPtr )
  335. {
  336.     AEDesc    docSpecifier;
  337.     AEDesc    fieldDescriptor;
  338.     AEDesc    nullDesc;
  339.     OSErr    err;
  340.  
  341.     /* Create an object specifier for a particular text field within a particular
  342.      * window. In each case use formAbsolutePosition.
  343.      */
  344.  
  345.     err = BuildCardSpecifier( &docSpecifier, cardNumber );
  346.     if ( err ){
  347.         Gripe( "\pBuildWindowDescriptor failed" );
  348.         return err;
  349.     }
  350.  
  351.     
  352. //    err = AECreateDesc( typeNull, (Ptr)NULL, (Size)0, &nullDesc );
  353. //    if ( err )
  354. //        return err;
  355.  
  356.     err = CreateOffsetDescriptor( fieldNumber, &fieldDescriptor );
  357.     if ( err ){
  358.         Gripe( "\pCreateOffsetDescriptor failed" );
  359.         return err;
  360.     }
  361.     
  362.     err = CreateObjSpecifier( 'cCFD',
  363.                                 &docSpecifier,
  364.                                 formAbsolutePosition,
  365.                                 &fieldDescriptor,
  366.                                 true,                        /* Dispose input descriptors */
  367.                                 specPtr );
  368.  
  369. //    err = CreateObjSpecifier( 'cCFD',
  370. //                                &nullDesc,
  371. //                                formAbsolutePosition,
  372. //                                &fieldDescriptor,
  373. //                                true,                        /* Dispose input descriptors */
  374. //                                specPtr );
  375.     if ( err ){
  376.         Gripe( "\pCreateObjSpecifer failed" );
  377.         return err;
  378.     }
  379.  
  380.     return noErr;
  381. }
  382.  
  383. void HandleStrToPStr( Handle h, StringPtr str )
  384. {
  385.     short    size;
  386.     char    *p;
  387.  
  388.     // Convert a handle to a C string into a Pascal string
  389.  
  390.     p = *h;
  391.     size = 0;
  392.  
  393.     while ( *p++ )
  394.         size++;
  395.     
  396.     if ( size > 255 )
  397.         size = 255;
  398.  
  399.     str[ 0 ] = (unsigned char)size;
  400.     
  401.     BlockMove( *h, &str[ 1 ], size );
  402.  
  403.     return;
  404. }